﻿using Mapster;
using Microsoft.AspNetCore.Mvc;
using PARK.Common.Core.Manager;
using PARK.Common.Enum;
using PARK.Common.Extension;
using PARK.Common.Filter;
using PARK.Consumer.Entity;
using PARK.Consumer.Entitys;
using PARK.Consumer.Entitys.Dto.ConsumMachine;
using PARK.Consumer.Interfaces;
using PARK.Dependency;
using PARK.DynamicApiController;
using PARK.FriendlyException;
using PARK.JsonSerialization;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yitter.IdGenerator;

namespace PARK.Consumer
{
    /// <summary>
    /// 消费机服务
    /// </summary>
    [ApiDescriptionSettings(Tag = "Consum", Name = "ConsumMachine", Order = 200)]
    [Route("api/consum/[controller]")]
    public class ConsumMachineService : IConsumMachineService, IDynamicApiController, ITransient
    {
        private readonly ISqlSugarRepository<ConsumMachineEntity> _consumMachineRepository;
        private readonly SqlSugarScope _db;
        private readonly IUserManager _userManager;

        /// <summary>
        /// 初始化一个<see cref="ConsumMachineService"/>类型的新实例
        /// </summary>
        public ConsumMachineService(
            ISqlSugarRepository<ConsumMachineEntity> consumMachineRepository,
            IUserManager userManager)
        {
            _consumMachineRepository = consumMachineRepository;
            _db = _consumMachineRepository.Context;
            _userManager = userManager;
        }

        /// <summary>
        /// 获取消费机
        /// </summary>
        /// <param name="id">参数</param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public async Task<dynamic> GetInfo(string id)
        {
            var entity = await _db.Queryable<ConsumMachineEntity>().FirstAsync(p => p.MachineId == id);
            var output = entity.Adapt<ConsumMachineInfoOutput>();
            return output;
        }

        /// <summary>
		/// 获取消费机列表
		/// </summary>
		/// <param name="input">请求参数</param>
		/// <returns></returns>
        [HttpGet("")]
        public async Task<dynamic> GetList([FromQuery] ConsumMachineListQueryInput input)
        {
            var userInfo = await _userManager.GetUserInfo();
            if (userInfo != null && userInfo.UserAdminFlag != 2 && !string.IsNullOrEmpty(userInfo.companyId))
            {
                var sidx = input.sidx == null ? "CreateDate" : input.sidx;
                List<string> queryInstallDate = input.installDate != null ? input.installDate.Split(',').ToObeject<List<string>>() : null;
                DateTime? startInstallDate = queryInstallDate != null ? Ext.GetDateTime(queryInstallDate.First()) : null;
                DateTime? endInstallDate = queryInstallDate != null ? Ext.GetDateTime(queryInstallDate.Last()) : null;
                var data = await _db.Queryable<ConsumMachineEntity>()
                    //公司权限
                    .Where(p => p.CompanyId.Equals(userInfo.companyId))
                    .Where(d => d.IsDeleted != 1)
                    .WhereIF(!string.IsNullOrEmpty(input.keyword), p => p.MachineNo.Contains(input.keyword) || p.MachineName.Contains(input.keyword) || p.MachineSerialNum.Contains(input.keyword) || p.IOTcardNo.Contains(input.keyword))
                    .WhereIF(!string.IsNullOrEmpty(input.machineNo), p => p.MachineNo.Contains(input.machineNo))
                    .WhereIF(!string.IsNullOrEmpty(input.machineName), p => p.MachineName.Contains(input.machineName))
                    .WhereIF(!string.IsNullOrEmpty(input.machineSerialNum), p => p.MachineSerialNum.Contains(input.machineSerialNum))
                    .WhereIF(!string.IsNullOrEmpty(input.merchantId), p => p.MerchantId.Equals(input.merchantId))
                    .WhereIF(queryInstallDate != null, p => p.InstallDate >= new DateTime(startInstallDate.ToDate().Year, startInstallDate.ToDate().Month, startInstallDate.ToDate().Day, 0, 0, 0))
                    .WhereIF(queryInstallDate != null, p => p.InstallDate <= new DateTime(endInstallDate.ToDate().Year, endInstallDate.ToDate().Month, endInstallDate.ToDate().Day, 23, 59, 59))
                    .WhereIF(!string.IsNullOrEmpty(input.installAddress), p => p.InstallAddress.Contains(input.installAddress))
                    .WhereIF(!string.IsNullOrEmpty(input.machineStatus), p => p.MachineStatus.Equals(input.machineStatus))
                    .WhereIF(!string.IsNullOrEmpty(input.isOnline), p => p.IsOnline.Equals(input.isOnline))
                    .Select(it => new ConsumMachineListOutput
                    {
                        machineId = it.MachineId,
                        machineNo = it.MachineNo,
                        machineName = it.MachineName,
                        machineSerialNum = it.MachineSerialNum,
                        merchantName = it.MerchantName,
                        installDate = it.InstallDate,
                        installAddress = it.InstallAddress,
                        machineStatus = it.MachineStatus,
                        remark = it.Remark,
                        isOnline = it.IsOnline,
                        lastOnLineTime = it.LastOnLineTime,
                        lastSyntime = it.LastSyntime,
                        CreateDate = it.CreateDate,
                        ioTcardNo = it.IOTcardNo
                    }).MergeTable().OrderBy(sidx + " " + input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
                return PageResult<ConsumMachineListOutput>.SqlSugarPageResult(data);
            }
            else
                return null;
        }

        /// <summary>
        /// 新建消费机
        /// </summary>
        /// <param name="input">参数</param>
        /// <returns></returns>
        [HttpPost("")]
        public async Task Create([FromBody] ConsumMachineCrInput input)
        {
            var userInfo = await _userManager.GetUserInfo();
            if (userInfo != null && userInfo.UserAdminFlag != 2 && !string.IsNullOrEmpty(userInfo.companyId))
            {
                var et = _db.Queryable<ConsumMachineEntity>() .Where(d => d.MachineName.Equals(input.machineName) && d.IsDeleted != 1 && d.CompanyId== userInfo.companyId) .ToList().FirstOrDefault();
                if (et != null)
                {
                    throw PARKException.Oh(ErrorCode.COM1004, "消费机名称[" + et.MerchantName + "：" + input.machineName + "]已存在！");
                }
                et = _db.Queryable<ConsumMachineEntity>().Where(d => d.MachineSerialNum.Equals(input.machineSerialNum) && d.IsDeleted != 1 && d.CompanyId == userInfo.companyId).ToList().FirstOrDefault();
                if (et != null)
                {
                    throw PARKException.Oh(ErrorCode.COM1004, "消费机SN[" + et.MerchantName + "：" + input.machineSerialNum + "]已存在！");
                }
                var merchant = _db.Queryable<ConsumMerchantEntity>().Where(d => d.IsDeleted != 1 && d.MerchantId.Equals(input.merchantId)).ToList().FirstOrDefault();
                var entity = input.Adapt<ConsumMachineEntity>();
                if (merchant == null)
                {
                    throw PARKException.Oh(ErrorCode.COM1010, "商户不存在！");
                }
                entity.MachineNo = YitIdHelper.NextId().ToString();
                entity.MachineId = YitIdHelper.NextId().ToString();
                entity.MerchantName = merchant.MerchantName;
                entity.CreateDate = entity.LastUpdateDate = DateTime.Now;
                entity.CreateUser = entity.LastUpdateUser = _userManager.User.Id;
                entity.CreateUserName = entity.LastUpdateUserName = _userManager.User.RealName;
                entity.CompanyId = userInfo.companyId;
                entity.CompanyName = userInfo.companyName;
                var isOk = await _db.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync();
                if (!(isOk > 0)) throw PARKException.Oh(ErrorCode.COM1000);
            }
            else
                throw PARKException.Bah("您的权限无法操作!");
        }

        /// <summary>
        /// 更新消费机
        /// </summary>
        /// <param name="id">主键</param>
        /// <param name="input">参数</param>
        /// <returns></returns>
        [HttpPut("{id}")]
        public async Task Update(string id, [FromBody] ConsumMachineUpInput input)
        {
            var userInfo = await _userManager.GetUserInfo();
            if (userInfo != null && userInfo.UserAdminFlag != 2 && !string.IsNullOrEmpty(userInfo.companyId))
            {
                var et = _db.Queryable<ConsumMachineEntity>()
                    .Where(d => d.MachineName.Equals(input.machineName) && d.IsDeleted != 1 && !d.MachineId.Equals(input.machineId) && d.CompanyId == userInfo.companyId)
                    .ToList().FirstOrDefault();
                if (et != null)
                {
                    throw PARKException.Oh(ErrorCode.CON1008, "消费机名称[" + et.MerchantName + "：" + input.machineName + "]已存在！");
                }
                et = _db.Queryable<ConsumMachineEntity>()
                    .Where(d => d.MachineSerialNum.Equals(input.machineSerialNum) && d.IsDeleted != 1 && !d.MachineId.Equals(input.machineId) && d.CompanyId == userInfo.companyId)
                    .ToList().FirstOrDefault();
                if (et != null)
                {
                    throw PARKException.Oh(ErrorCode.CON1009, "消费机SN[" + et.MerchantName + "：" + input.machineSerialNum + "]已存在！");
                }
                var merchant = _db.Queryable<ConsumMerchantEntity>().Where(d => d.IsDeleted != 1 && d.MerchantId.Equals(input.merchantId)).ToList().FirstOrDefault();
                var entity = input.Adapt<ConsumMachineEntity>();
                entity.MerchantName = merchant.MerchantName;
                entity.LastUpdateDate = DateTime.Now;
                entity.LastUpdateUser = _userManager.User.Id;
                entity.LastUpdateUserName = _userManager.User.RealName;
                entity.CompanyId = userInfo.companyId;
                entity.CompanyName = userInfo.companyName;
                var isOk = await _db.Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
                if (!(isOk > 0)) throw PARKException.Oh(ErrorCode.COM1001);
            }
            else
                throw PARKException.Bah("您的权限无法操作!");
        }

        /// <summary>
        /// 删除消费机
        /// </summary>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public async Task Delete(string id)
        {
            var userInfo = await _userManager.GetUserInfo();
            if (userInfo != null && userInfo.UserAdminFlag != 2 && !string.IsNullOrEmpty(userInfo.companyId))
            {
                var entity = await _db.Queryable<ConsumMachineEntity>().FirstAsync(p => p.MachineId == id);
                _ = entity ?? throw PARKException.Oh(ErrorCode.COM1005);
                entity.DeleteUser = _userManager.User.Id;
                entity.DeleteUserName = _userManager.User.RealName;
                entity.DeleteDate = DateTime.Now;
                entity.IsDeleted = 1;
                var isOk = await _db.Updateable(entity).UpdateColumns(d => new { d.DeleteDate, d.IsDeleted, d.DeleteUser }).ExecuteCommandAsync();
                if (!(isOk > 0)) throw PARKException.Oh(ErrorCode.COM1002);
            }
            else
                throw PARKException.Bah("您的权限无法操作!");
        }
        /// <summary>
        /// 给消费机下发名单
        /// </summary>
        /// <returns></returns>
        [HttpPost("EyeTaskMachineini")]
        public async Task EyeTaskMachineini(string id)
        {
            var userInfo = await _userManager.GetUserInfo();
            if (userInfo != null && userInfo.UserAdminFlag != 2 && !string.IsNullOrEmpty(userInfo.companyId))
            {
                var Paras = new List<SugarParameter>();
                Paras.Add(new SugarParameter("@MachineId", id));
                Paras.Add(new SugarParameter("@upflag", null, true));
                _db.Ado.UseStoredProcedure().ExecuteCommand("P_EyeTaskMachine_Ini", Paras);
                object _obj = Paras[1].Value;
                if (_obj == null)
                {
                    if (int.Parse(_obj.ToString()) == -1)
                    {
                        throw PARKException.Bah("当前咱无可下发名单!");
                    }
                    else if(int.Parse(_obj.ToString()) ==0)
                    {
                        throw PARKException.Bah("处理下发名单失败!");
                    }
                } 
            }
            else
                throw PARKException.Bah("您的权限无法操作!");
        }

        #region 获取消费设备状态统计
        /// <summary>
        /// 获取消费设备状态统计
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("GetmachineStatusCenQtys")]
        public async Task<dynamic> GetmachineStatusCenQtys([FromQuery] MachineMachsListQueryInput input)
        {
            var userInfo = await _userManager.GetUserInfo();
            try
            {
                StringBuilder dbSql = new StringBuilder("select isOnline,count(0) as qty from consum_machine t where IsDeleted=0 ");

                #region 查询条件
                if (!string.IsNullOrEmpty(input.keyword))
                {
                    dbSql.AppendFormat(" AND (t.MachineName like '%{0}%' or t.MachineSerialNum like '%{0}%' or t.MachineNo like '%{0}%')", input.keyword);
                }
                #endregion

                //公司权限
                dbSql.AppendFormat(" and CompanyId='{0}'", userInfo.companyId);

                dbSql.Append(" group by t.isOnline");
                var data = await _db.SqlQueryable<DataTable>(dbSql.ToString()).ToDataTableAsync();
                MachineStatusCenQtyOutput _output = new MachineStatusCenQtyOutput();
                _output.onlineQty = 0;
                _output.offlineQty = 0;
                DataRow[] dr = data.Select("isOnline=0");
                if (dr != null && dr.Length > 0)
                {
                    _output.offlineQty = int.Parse(dr[0]["qty"].ToString());
                }
                dr = data.Select("isOnline=1");
                if (dr != null && dr.Length > 0)
                {
                    _output.onlineQty = int.Parse(dr[0]["qty"].ToString());
                }
                return _output;
            }
            catch (Exception)
            {
                throw PARKException.Oh("获取数据异常");
            }
        }
        #endregion

        /// <summary>
        /// 获取某商户下消费机下拉
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetMerMachSelector")]
        public async Task<dynamic> GetMerMachSelector(string MerchantId)
        {
            var userInfo = await _userManager.GetUserInfo();
            var treeList = new List<ConsumMachineCrInput>();
            var data = await _db.Queryable<ConsumMachineEntity>().Where(t => t.IsDeleted == 0 && t.MerchantId == MerchantId)
                    //公司权限
                    .Where(p => p.CompanyId.Equals(userInfo.companyId))
                .ToListAsync();
            data.ForEach(item =>
            {
                treeList.Add(new ConsumMachineCrInput()
                {
                    machineId = item.MachineId,
                    machineName = item.MachineName,
                });
            });
            return new { list = treeList };
        }
    }
}
